﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using BaseApplicationNamespace;
using MainApplicationNamespace.Entity1s;
using MainDomainNamespace.Entity1s;

namespace MainApplicationNamespace
{
    /// <summary>
    /// Facade1 ファサードを表します。
    /// </summary>
    [Serializable]
    public sealed class Facade1 : WorkFacade
    {
        /// <summary>
        /// <see cref="Facade1"/> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="mode">作業モード。</param>
        public Facade1(WorkMode? mode = null)
            : base(WorkspaceSelector.Get(mode))
        {
        }


        /// <summary>
        /// 現在クライアントに提供されている <see cref="Entity1"/> の一覧を取得または設定 (private) します。
        /// </summary>
        public ReadOnlyCollection<Entity1> Entity1List
        {
            get;
            private set;
        }


        /// <summary>
        /// ファサードの状態が更新されると発生します。
        /// </summary>
        public event EventHandler Refreshed;

        /// <summary>
        /// <see cref="Entity1"/> の一覧読み込みが失敗すると発生します。
        /// </summary>
        public event ErrorEventHandler<Entity1ListLoadErrors> Entity1ListLoadError;

        /// <inheritdoc/>
        protected override void OnInitialize()
        {
            LoadEntity1List();
        }

        /// <summary>
        /// <see cref="Entity1"/> の一覧を読み込みます。
        /// </summary>
        /// <param name="raiseRefreshedEvent"><see cref="Refreshed"/> イベントを発生させるかどうかを示す値。</param>
        private void LoadEntity1List(bool raiseRefreshedEvent = true)
        {
            var script = new Entity1ListLoadScript(Workspace);
            script.Success += (sender, e) =>
            {
                Entity1List = new ReadOnlyCollection<Entity1>(e.Outputs.List);
                if (raiseRefreshedEvent && (Refreshed != null))
                {
                    Refreshed(this, EventArgs.Empty);
                }
            };
            script.Error += Entity1ListLoadError;
            script.Execute();
        }


        /// <summary>
        /// <see cref="Entity1"/> の作成を目的として、<see cref="Entity1.Builder">Entity1 ビルダ</see>を生成します。
        /// </summary>
        /// <returns><see cref="Entity1.Builder">Entity1 ビルダ</see>。</returns>
        public Entity1.Builder CreateEntity1Builder()
        {
            var repository = Workspace.GetRepository<Entity1>();
            var validator = new Entity1ConstraintValidator(repository);
            return new Entity1.Builder(validator);
        }

        /// <summary>
        /// <see cref="Entity1"/> の編集を目的として、<see cref="Entity1.Builder">Entity1 ビルダ</see>を生成します。
        /// </summary>
        /// <param name="entity1">編集対象の <see cref="Entity1"/>。</param>
        /// <returns><see cref="Entity1.Builder">Entity1 ビルダ</see>。</returns>
        public Entity1.Builder CreateEntity1Builder(Entity1 entity1)
        {
            var repository = Workspace.GetRepository<Entity1>();
            var validator = new Entity1ConstraintValidator(repository);
            return new Entity1.Builder(entity1, validator);
        }

        /// <summary>
        /// <see cref="Entity1"/> の作成を実行します。
        /// </summary>
        /// <param name="builder"><see cref="Entity1.Builder">Entity1 ビルダ</see>。</param>
        /// <param name="errorHandler">エラーハンドラ。</param>
        public void ExecuteEntity1Creation(Entity1.Builder builder, Action<EntityCreationErrors> errorHandler)
        {
            var script = new EntityCreationScript<Entity1>(Workspace);
            script.Builder = builder;
            script.Success += (sender, e) =>
            {
                LoadEntity1List();
            };
            script.Error += (sender, e) =>
            {
                errorHandler(e.Errors);
                e.Errors.HandledBy(CommitmentErrorsHandler);
            };
            script.Execute();
        }

        /// <summary>
        /// <see cref="Entity1"/> の編集を実行します。
        /// </summary>
        /// <param name="builder"><see cref="Entity1.Builder">Entity1 ビルダ</see>。</param>
        /// <param name="errorHandler">エラーハンドラ。</param>
        public void ExecuteEntity1Edition(Entity1.Builder builder, Action<EntityEditionErrors> errorHandler)
        {
            var script = new EntityEditionScript<Entity1>(Workspace);
            script.Builder = builder;
            script.Success += (sender, e) =>
            {
                LoadEntity1List();
            };
            script.Error += (sender, e) =>
            {
                errorHandler(e.Errors);
                e.Errors.HandledBy(CommitmentErrorsHandler);
            };
            script.Execute();
        }

        /// <summary>
        /// <see cref="Entity1"/> の削除を実行します。
        /// </summary>
        /// <param name="targets">削除対象の <see cref="Entity1"/> の一覧。</param>
        /// <param name="errorHandler">エラーハンドラ。</param>
        public void ExecuteEntity1Deletion(IEnumerable<Entity1> targets, Action<EntityDeletionErrors> errorHandler)
        {
            var script = new EntityDeletionScript<Entity1>(Workspace);
            script.Targets = targets;
            script.Success += (sender, e) =>
            {
                LoadEntity1List();
            };
            script.Error += (sender, e) =>
            {
                errorHandler(e.Errors);
                e.Errors.HandledBy(CommitmentErrorsHandler);
            };
            script.Execute();
        }
    }
}
